//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#include "ProcessListCATHCodeToDonutChart.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <fstream>
#include <iostream>
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
using namespace std;
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
typedef enum Levels {C,A,T,H,S,O,L,I,D} Levels;
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#define MAX_SIZE 500000
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
namespace CATHCodeToDonutChart {
  
  bool EqualSegment (TNode <DonutStatistic>* segment, void* ref) {

    return (!strncmp(segment->Info()->Level()->Out(), (char*)ref, strlen((char*)ref)))?true:false;

  }
  
};
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ProcessListCATHCodeToDonutChart::ProcessListCATHCodeToDonutChart () {

  this->filenameOut  = new String ();
  this->filenameIn   = new String ();
  this->listCATHCode = new TListE <String> ();
  
  for (int i = C; i <= D; i++)
    this->listDonutStatistic[i] = new TListE <DonutStatistic> ();

  this->toString     = new String ();

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ProcessListCATHCodeToDonutChart::ProcessListCATHCodeToDonutChart (const ProcessListCATHCodeToDonutChart& processListCATHCodeToDonutChart) {

  this->filenameOut  = new String (processListCATHCodeToDonutChart.filenameOut);
  this->filenameIn   = new String (processListCATHCodeToDonutChart.filenameIn);
  this->listCATHCode = new TListE <String> (processListCATHCodeToDonutChart.listCATHCode);
  
  for (int i = C; i <= D; i++)
    this->listDonutStatistic[i] = new TListE <DonutStatistic> (processListCATHCodeToDonutChart.listDonutStatistic[i]);

  this->toString     = new String (processListCATHCodeToDonutChart.toString);

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ProcessListCATHCodeToDonutChart::ProcessListCATHCodeToDonutChart (const ProcessListCATHCodeToDonutChart* processListCATHCodeToDonutChart) {

  this->filenameOut  = new String (processListCATHCodeToDonutChart->filenameOut);
  this->filenameIn   = new String (processListCATHCodeToDonutChart->filenameIn);
  this->listCATHCode = new TListE <String> (processListCATHCodeToDonutChart->listCATHCode);

  for (int i = C; i <= D; i++)
    this->listDonutStatistic[i] = new TListE <DonutStatistic> (processListCATHCodeToDonutChart->listDonutStatistic[i]);

  this->toString     = new String (processListCATHCodeToDonutChart->toString);

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ProcessListCATHCodeToDonutChart::~ProcessListCATHCodeToDonutChart () {

  if (this->filenameOut)        delete this->filenameOut;
  if (this->filenameIn)         delete this->filenameIn;
  if (this->listCATHCode)       delete this->listCATHCode;

  for (int i = C; i <= D; i++)
    if (this->listDonutStatistic[i]) 
      delete this->listDonutStatistic;

  if (this->toString)           delete this->toString;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ProcessListCATHCodeToDonutChart::FilenameOut (String* filenameOut) {

  if (filenameOut)
    *(this->filenameOut) = *filenameOut;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ProcessListCATHCodeToDonutChart::FilenameIn (String* filenameIn) {

  if (filenameIn)
    *(this->filenameIn) = *filenameIn;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ProcessListCATHCodeToDonutChart::ListDonutStatistic (TListE <DonutStatistic>* listDonutStatistic [9]) {

  for (int i = A; i <= D; i++)
    if (listDonutStatistic[i])
      *(this->listDonutStatistic[i]) = *listDonutStatistic[i];

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ProcessListCATHCodeToDonutChart::ListCATHCode (TListE <String>* listCATHCode) {

  if (listCATHCode)
    *(this->listCATHCode) = *listCATHCode;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//

String* ProcessListCATHCodeToDonutChart::FilenameOut (void) {

  return this->filenameOut;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* ProcessListCATHCodeToDonutChart::FilenameIn (void) {

  return this->filenameIn;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
TListE <DonutStatistic>** ProcessListCATHCodeToDonutChart::ListDonutStatistic (void) {

  return this->listDonutStatistic;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
TListE <String>* ProcessListCATHCodeToDonutChart::ListCATHCode (void) {

  return this->listCATHCode;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* ProcessListCATHCodeToDonutChart::ToString (void) {

  ;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ProcessListCATHCodeToDonutChart::LoadFileCATHCode (void) {

  if (!this->filenameIn || !this->filenameIn->Length())
    return false;
  
  ifstream file (this->filenameIn->Out());
  
  if (!file.is_open())
    return false;
  
  char buffer [MAX_SIZE];
  
  while (!file.eof()) {
    
    file.getline(buffer, MAX_SIZE);
    
    String* newCATHCode = new String (buffer);
    newCATHCode->RTrim();
    
    if (!newCATHCode->Length()) {
      delete newCATHCode;
      continue;
    }
    
    this->listCATHCode->Add(newCATHCode);
    
  }
  
  file.close();
  
  return this->ComputePercentages();

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ProcessListCATHCodeToDonutChart::WriteStatisticData (void) {


}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ProcessListCATHCodeToDonutChart::ComputePercentages (void) {
  
  if (!this->listCATHCode || !this->listCATHCode->Length())
    return false;
  
  for (int i = A; i <= D; i++)
    (this->listDonutStatistic[i])->Clear();
  
  char* segment = NULL;
  
  for (int i = A; i < D; i++) {
    
    this->listCATHCode->SetInitial();
    while (this->listCATHCode->SetNext()) {
      
      this->GetSegmentUntilPosition(this->listCATHCode->GetCurrent()->Out(), i + 1, '.', segment);
      String* search = this->listDonutStatistic[i]->FirstOcurrence(CATHCodeToDonutChart::EqualSegment, segment);
      
      if (!search) {
        DonutStatistic* newDonutStatistic = new DonutStatistic ();
        newDonutStatistic->Level(new String(segment));
        this->listDonutStatistic[i]->Add(newDonutStatistic);
      }
      
    }
    
  }
  
  if (segment) delete[] segment;
  
  this->listCATHCode->SetInitial();
  while (this->listCATHCode->SetNext()) {
    DonutStatistic* newDonutStatistic = new DonutStatistic ();
    newDonutStatistic->Level(new String(this->listCATHCode->GetCurrent()->Out()));
    this->listDonutStatistic[D]->Add(newDonutStatistic);
  }
  
  for (int i = A; i <= D; i++) {
    
    this->listDonutStatistic[i]->SetInitial();
    while (this->listDonutStatistic[i]->SetNext()) {
      
      this->listDonutStatistic[i]->GetCurrent();
      
      
    }
    
  }
  
  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ProcessListCATHCodeToDonutChart::GetSegmentInPosition (char* text, int position, char* separators, char* result) {
  
  if (position < 0 || !text || !separators)
    return false;
    
  int   counter = 0;
  
  char  tmp [strlen(text) + 1];
  char* parts = NULL;
  
  strcpy(tmp, text);
  
  if (result) delete[] result;
  
  parts = strtok(tmp, separators);
  while (parts) {
    
    if (++counter == position) {
      result = new char [strlen(parts) + 1];
      strcpy(result, parts);    
      result[strlen(parts)] = '\0';
      return true;
    }
    
    parts = strtok(NULL, separators);
    
  }
  
  return false;
    
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ProcessListCATHCodeToDonutChart::GetSegmentUntilPosition (char* text, int position, char separator, char* result) {
  
  if (position < 0 || !text)
    return false;
    
  int   counter = 0;
  char  tmp [strlen(text) + 1];
  char* pch = NULL;
  
  strcpy(tmp, text);
  
  if (result) delete[] result;
  
  pch = strchr(tmp, separator);
  
  while (pch) {
    if (++counter == position) {
      result = new char [pch - tmp + 1];
      strncpy(result, text, pch - tmp);
      result[pch - tmp] = '\0';
      return true;
    }
    pch = strchr(pch + 1, separator);
  }  

  return false;
    
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ProcessListCATHCodeToDonutChart ProcessListCATHCodeToDonutChart::operator= (const ProcessListCATHCodeToDonutChart& processListCATHCodeToDonutChart) {

  *(this->filenameOut)  = *(processListCATHCodeToDonutChart.filenameOut);
  *(this->filenameIn)   = *(processListCATHCodeToDonutChart.filenameIn);
  *(this->listCATHCode) = *(processListCATHCodeToDonutChart.listCATHCode);
  
  for (int i = A; i <= D; i++)
    *(this->listDonutStatistic[i]) = *(processListCATHCodeToDonutChart.listDonutStatistic[i]);

  *(this->toString)     = *(processListCATHCodeToDonutChart.toString);

  return *this;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
